#  Copyright (c) 2020 - ~, WANGXI
#  
#  NS GRAMMA NS2 EXAMPLE TCL FILE
#  Used in NS-2 simulator
#  Clone from https://gitee.com/WangXi_Chn/ns2_modulelib
#  Note in https://www.yuque.com/wangxi_chn/kozrfl
#  
#  Change Logs:
#  Date           Author       Notes			Mail
#  2020-12-08     WangXi   	   first version	WangXi_Chn@foxmail.com

# Create a simulator object
# 产生一个NS2模拟对象的实例
# 1. 包格式的初始化
# 2. 产生一个事件调度计划
# 3. 选择一个默认的地址格式
set ns [new Simulator]

# simulator 对象有以下几个性质
# 1. 产生组件对象，比如节点和链路
# 2. 连接已经创建的网络组件对象
# 3. 设置网络组件参数
# 4. 在代理之间建立链接
# 5. 指定NAM显示选项等
# 大多数的成员函数是用于模拟设置和事件调度的，但是也有一些用于NAM显示
# Simulator 的成员函数在文件 ns/tcl/lib/ns-lib.tcl中

# Define different colors for data flows(for NAM)
# 设置每个数据流的颜色
$ns color 1 Blue
$ns color 2 Red

# Open the NAM trace file
# 让模拟器以NAM的输入格式记录模拟结果
# 同时还给出了后续由 $ns flush-trace 命令写入的跟踪文件的文件名
# 成员函数trace-all 是用以常规格式记录模拟过程
set nf [open out.nam w]
$ns namtrace-all $nf

set tr [open out.tr w]
$ns trace-all $tr
$ns eventtrace-all $tr

# Define a finish procedure
# 这个过程是在命令$ns at 5.0 "finish"后被调用
proc finish {} {
    global ns nf
    $ns flush-trace
    # Close the NAM trace file
    close $nf
    # Execulte nam on the trace file
    exec nam out.nam &
    exit 0
}

# Create four nodes
# 成员函数node用来创建一个节点
# 在ns中一个节点是一个组件对象
# 该组件对象由地址和端口组成，用户可以通过将地址和端口分别定义的对象来定义一个节点
# 然后将它们连接在一起
# 可通过研究ns/tcl/lib/ns-lib.tcl和ns/tcl/lib/ns-node.tcl了解一个节点如何被创建
set n0 [$ns node]
set n1 [$ns node]
set n2 [$ns node]
set n3 [$ns node]


# Give node style (for NAM)
# 设置NAM中的节点显示风格
$n0 color red
$n0 shape square
$n0 label "node0"
$n0 label-color red

$n1 color blue
$n1 shape circle
$n1 label "node1"
$n1 label-color blue

$n2 color black
$n2 shape hexagon

$n3 color green

# Create links between the nodes
# 创建两个已经定义的节点之间的双向链路
# 并对每个链路定义其带宽和延时
# 在NS2中节点的队列输出被当作链路的一部分
# 当用户创建一个链路时，需要定义队列的类型（DropTail/RED）
# 链路也是一个组件对象，可创建子对象并且和节点连接
# ns/tcl/lib/ns-lib.tcl和ns/tcl/lib/ns-link.tcl
$ns duplex-link $n0 $n2 2MB 10ms DropTail
$ns duplex-link $n1 $n2 2MB 10ms DropTail
$ns duplex-link $n2 $n3 1.7MB 20ms DropTail

# Set Queue Size of link (n2-n3) to 10
# 设置两个节点之间链路的队列限制
# ns/tcl/lib/ns-lib.tcl和ns/tcl/lib/ns-link.tcl
$ns queue-limit $n2 $n3 10

# Give node position (for NAM)
# 设置NAM中的链路显示风格
$ns duplex-link-op $n0 $n2 orient right-down
$ns duplex-link-op $n1 $n2 orient right-up
$ns duplex-link-op $n2 $n3 orient right

$ns duplex-link-op $n0 $n2 color red
$ns duplex-link-op $n0 $n2 label "link 0-2"
$ns duplex-link-op $n0 $n2 label-color red

$ns duplex-link-op $n1 $n2 color blue
$ns duplex-link-op $n1 $n2 label "link 1-2"
$ns duplex-link-op $n1 $n2 label-color blue

# Monitor the queue for link (n2-n3). (for NAM)
$ns duplex-link-op $n2 $n3 queuePos 0.5

# Set a TCP connection
# 创建TCP代理，通常情况下用户可以使用这种方法创建任何代理或传输源
# 代理和传输源都在基本的对象中（不是在混合对象中）
# 通常是在C++中执行，并和OTcl连接
# 因此没有特别的模拟器对象的成员函数来创建这些对象的实例
# 为了创建代理或传输源，用户必须要用类来命名对象（如Agent/TCP，Agent/TCP-Sink，Application/FTP）
# 使用说明在NS-2文档有描述，可在ns/tcl/lib/ns-default.tcl快速了解默认配置
set tcp [new Agent/TCP]
$tcp set class_ 2
$tcp set fid_ 1
# attach-agent成员函数在一个节点对象上附加一个代理对象
# 即将给定的代理绑定在节点上
$ns attach-agent $n0 $tcp
set sink [new Agent/TCPSink]
$ns attach-agent $n3 $sink
# 当两个需要相互通信的代理创建后，接下来就要在这两个代理之间建立一个逻辑的网络链路
# 不同于duplex-link建立的实体链路
$ns connect $tcp $sink


#Setup a FTP over TCP connection
set ftp [new Application/FTP]
$ftp attach-agent $tcp
$ftp set type_ FTP

#Setup a UDP connection
set udp [new Agent/UDP]
$ns attach-agent $n1 $udp
set null [new Agent/Null]
$ns attach-agent $n3 $null
$ns connect $udp $null
$udp set fid_ 2

#Setup a CBR over UDP connection
set cbr [new Application/Traffic/CBR]
$cbr attach-agent $udp
$cbr set type_ CBR
$cbr set packet_size_ 1000
$cbr set rate_ 1mb
$cbr set random_ false

#Schedule events for the CBR and FTP agents
# 创建一个事件调度计划在指定的模拟时间开始执行指定的字符串
# 例如下句：创建一个事件调度计划调用CBR传输源对象，并启动CBR进行数据传输
$ns at 0.1 "$cbr start"
$ns at 1.0 "$ftp start"
$ns at 4.0 "$ftp stop"
$ns at 4.5 "$cbr stop"
# 在NS2中通常一个传输源是不传输真实的数据的，但是它通知下面的代理有数据需要传输
# 然后这个代理获知要传输数据的数据量，创建数据包并传输数据

#Detach tcp and sink agents (not really necessary)
$ns at 4.5 "$ns detach-agent $n0 $tcp ; $ns detach-agent $n3 $sink"

#Call the finish procedure after 5 seconds of simulation time
$ns at 5.0 "finish"

#Print CBR packet size and interval
puts "CBR packet size = [$cbr set packet_size_]"
puts "CBR interval = [$cbr set interval_]"

#Run the simulation
$ns run


















#/************************ (C) COPYRIGHT 2020 WANGXI **************END OF FILE****/
